package org.softmed.rest.server.defaults.handlers;

import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;
import groovy.lang.Binding;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.softmed.action.Action;
import org.softmed.action.exception.SimpleException;
import org.softmed.action.exception.StopException;
import org.softmed.action.manager.ActionManager;
import org.softmed.action.workarea.WorkArea;
import org.softmed.filehandling.FileUtil;
import org.softmed.rest.config.Handler;
import org.softmed.rest.config.Parameter;
import org.softmed.rest.server.core.handler.HandlerProcessParameters;
import org.softmed.rest.server.core.handler.SpecificHandlerSolver;

import com.google.inject.Inject;

public class ActionSolver implements SpecificHandlerSolver {
	FileUtil util = new FileUtil();

	@Inject
	ActionManager actionManager;

	boolean stop = false;

	@Override
	public boolean canSolve(Handler handler) {

		String path = handler.getPath();

		path = path.replace('.', '/');
		path += ".xml";

		// if (util.fileExists(path))
		// return true;
		// else
		// return false;
		File file = util.getFile(path);
		if (file == null || !file.exists())
			return false;

		return true;
	}

	@Override
	public void solve(Handler handler, HandlerProcessParameters parameters)
			throws Throwable {

		String path = handler.getPath();

		path = path.replace('.', '/');
		path += ".xml";

		Action action = actionManager.getAction(path, handler, parameters);
		WorkArea workArea = action.getWorkArea();

		// set handler parameters
		List<Parameter> params = handler.getParameters();
		for (Parameter parameter : params) {
			if (parameter.isActive())
				workArea
						.setAttribute(parameter.getName(), parameter.getValue());
			else
				workArea.setAttribute(parameter.getName(), null);
		}

		Set<Entry<String, Object>> entries = parameters.getSequenceParameters()
				.entrySet();
		for (Entry<String, Object> entry : entries) {
			workArea.setAttribute(entry.getKey(), entry.getValue());
		}

		// TODO use java reflection to dynamize this
		workArea.setAttribute("application", parameters.getApplication());
		workArea.setAttribute("module", parameters.getModule());
		workArea.setAttribute("httpMethod", parameters.getHttpMethod());
		workArea.setAttribute("mimeTypeHandler", parameters
				.getMimeTypeHandler());
		workArea.setAttribute("resource", parameters.getResource());
		workArea.setAttribute("request", parameters.getRequest());
		workArea.setAttribute("response", parameters.getResponse());

		workArea.setAttribute("sequenceParameters", parameters
				.getSequenceParameters());
		workArea.setAttribute("uriParameters", parameters.getUriParameters());
		workArea.setAttribute("queryParameters", parameters
				.getQueryParameters());

		workArea.setAttribute("parameters", handler.getParametersAsMap());

//		if (!action.isPossible()) {
//			if (action.getTest().getException() != null) {
//				if (action.getTest().getException() instanceof StopException)
//					return;
//
//				if (action.getTest().getException() instanceof SimpleException) {
//					parameters.getResponse().setStatus(
//							Status.CLIENT_ERROR_FORBIDDEN);
//					parameters.getResponse().setEntity(
//							action.getTest().getException().getMessage(),
//							MediaType.TEXT_PLAIN);
//					return;
//				}
//
//			}
//			parameters.getResponse().setStatus(Status.CLIENT_ERROR_FORBIDDEN);
//			parameters.getResponse().setEntity(
//					"Request could not be executed.", MediaType.TEXT_PLAIN);
//			return;
//
//		}
		try {
			action.run();
		} catch (StopException t) {
			System.out.println("Execution Stopped");
		} catch (SimpleException t) {
			System.out.println("Execution Stopped");
			parameters.getResponse().setStatus(Status.CLIENT_ERROR_FORBIDDEN);
			parameters.getResponse().setEntity(t.getMessage(),
					MediaType.TEXT_PLAIN);
		}

		workArea.getValues().remove("sequenceParameters");
		workArea.getValues().remove("parameters");
		workArea.getValues().remove("queryParameters");
		workArea.getValues().remove("uriParameters");
		workArea.getValues().remove("response");
		workArea.getValues().remove("request");

		workArea.getValues().remove("httpMethod");
		workArea.getValues().remove("mimeTypeHandler");

		workArea.getValues().remove("resource");
		workArea.getValues().remove("module");
		workArea.getValues().remove("application");

		// List<Parameter> params = handler.getParameters();
		for (Parameter parameter : params) {
			workArea.getValues().remove(parameter.getName());
		}

		parameters.getSequenceParameters().clear();
		Set<Entry<String, Object>> remainingVariables = workArea.getValues()
				.entrySet();
		for (Entry<String, Object> entry : remainingVariables) {
			parameters.getSequenceParameters().put(entry.getKey(),
					entry.getValue());
		}

		try {
			Binding binding = (Binding) action.getWorkArea().getAttribute(
					"binding");
			if (binding == null)
				return;
			stop = (Boolean) binding.getVariable("stop");
			System.out.println("Stop processing = " + stop);
		} catch (Throwable t) {
			// t.printStackTrace();
		}

	}

	@Override
	public boolean isContinueProcessing() {
		// TODO Auto-generated method stub
		return !stop;
	}

	@Override
	public ActionSolver getClone() {
		ActionSolver clone = new ActionSolver();
		clone.actionManager = actionManager;
		return clone;
	}

}
